Skip to content

Footer: scroll a loop bound, collapse everything at once, drop the Alpha badge - #547

Merged
thcp merged 2 commits into
0.16.1from
feat/collapse-all-panels
Sep 1, 2026
Merged

Footer: scroll a loop bound, collapse everything at once, drop the Alpha badge#547
thcp merged 2 commits into
0.16.1from
feat/collapse-all-panels

Conversation

@thcp

@thcp thcp commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Closes #546
Closes #548
Closes #549

Three footer changes, all found while testing 0.16.1 on a Windows build, all landing in the same handful of files.

Clearing the studio took four presses in two places (#546)

#480 gave each panel around the mixer a toggle. Collapsing all three still left the library holding its column, which is the largest single thing on screen that is not the mixer, so it barely changed what you see. A bare mixer meant three presses in the toggles row plus a fourth on a control somewhere else.

The row now reads Collapse │ All - Analysis - Sections - Timeline. "Collapse" is a one-word label, not the sentence it had no width for, and the rule sits after it so All reads as the first of four buttons rather than part of the words describing them.

All greys and strikes through like the other three, but only once all four are away. That threshold is the whole trick: read as "is anything hidden" it struck itself through the moment Analysis was hidden on its own, which looks exactly like you pressed it.

It stores nothing. Its state is derived from .app, so there is no fourth flag to drift from the other three, and a MutationObserver on that one class keeps it right when the library is collapsed from its own button instead.

The refactor it needed

setSidebarCollapsed lived inside wireCatalogToggle's scope. It is exported now, because the sidebar's state is one class plus one localStorage flag and two writers reproducing that pair is how it drifts.

setCatalogView was already the second writer. It removed cat-collapsed and wrote the flag by hand but left the collapse button's aria-expanded claiming the sidebar was still shut. It routes through the helper now.

Trimming a loop bound meant retyping nine characters (#548)

A loop is never right first time. You drag a rough region, play it, and want the start forty milliseconds earlier because it clips the transient. Doing that meant clicking into the field and retyping 00:12.480 as 00:12.440, which is slower and less precise than dragging the region again, so the exact fields went unused for the one job they are best at.

The wheel adjusts them now:

  • left of the decimal point adjusts seconds, a tenth of a second per notch
  • right of it adjusts milliseconds, a hundredth per notch

One millisecond per notch would need a hundred notches to cover something audible.

Character-level hit-testing inside an <input> is not reliable across browsers, caretRangeFromPoint returns the element rather than an offset inside it. Only the decimal point matters here, so the text up to it is measured and compared against the pointer. The field is centre-aligned with symmetric padding, so the border box and the content box share a centre.

A nudge past either end of the track, or one that would squeeze the loop under MIN_LOOP_SEC, is dropped rather than clamped, so holding the wheel against the end of a track does not quietly drag the other bound along. The wheel event is consumed so it does not reach the lane zoom (#493) or scroll the page.

The fields take an ns-resize cursor, back to a caret once focused, and a label above them says what the wheel does. It is a label and not a control: there is nothing to press, and something that looks pressable and is not is worse than a plain note.

Loop itself moved beside the two bounds instead of sitting over them. As a row of its own it stretched the footer to three lines for one button.

Click track still carried an Alpha badge (#549)

It has been through several releases and has its own spec. The badge was the loudest thing in that corner of the footer, telling people the metronome might not work for a reason that stopped being true. A warning that is no longer true also teaches people to ignore the next one.

Removed properly rather than hidden: the markup, the .alpha-badge rule which had no other user, and the dead click.alpha key in all ten tables.

i18n

panels.all, panels.allTitle, panels.collapse and position.loopScrollHint added, position.loopLabel shortened to "Loop", panels.clickToCollapse and click.alpha removed as dead. ptPT carries one override: European Portuguese does not use "rolar" for scrolling a control.

en: complete (494 own keys)          fr: complete (494 own keys)
pl: complete (494 own keys)          ptPT (+pt): complete (101 own keys)
ja: complete (494 own keys)          es: complete (494 own keys)
zhHans: complete (494 own keys)      ko: complete (494 own keys)
de: complete (494 own keys)          clean
pt: complete (494 own keys)
id: complete (494 own keys)

Verification

playwright        85 passed (1.9m)
node tests/js/*   11/11
node --check      transport.js, ui-chrome.js, i18n.js, catalog.js clean
i18n audit        clean

All three were driven by hand on a packaged Windows build and adjusted from what that showed: the strikethrough threshold, the row order, the Loop button's placement and the footer's vertical alignment all came from looking at it rather than from the first guess.

No automated coverage for the wheel adjustment or the All button yet. Both are DOM-level behaviours that would need a Playwright spec, and neither has one.

Thales added 2 commits September 1, 2026 10:20
#480 gave each panel around the mixer a toggle, but collapsing all three
still left the library holding its column, which is the largest thing on
screen that is not the mixer. Getting to a bare mixer meant three presses
in the toggles row and a fourth on a control somewhere else, then four
more to undo it.

"All" sits at the end of the same row and takes the three panels and the
sidebar together. It keeps no state of its own: it drives the same
apply/persist the individual toggles already use, and reads its own
pressed state back off .app. A fourth flag would be a fourth thing to
disagree with the other three the moment the library was collapsed from
its own button instead. A MutationObserver on that one class attribute is
what keeps it honest, so no other handler has to remember it exists.

setSidebarCollapsed moves out of wireCatalogToggle's scope and is
exported, because the sidebar's state is one class plus one localStorage
flag and two writers reproducing that pair is how it drifts.
setCatalogView was already the second writer: it wrote the flag by hand
and left the collapse button's aria-expanded claiming the sidebar was
still shut. It routes through the helper now.

panels.all and panels.allTitle are in all ten language tables. ptPT needs
no override, the European wording is the same.
Three things in the footer, all of them small and all of them in the same
three files.

A loop bound could only be changed by typing it. A loop is never right
first time: you drag a rough region, play it, and want the start forty
milliseconds earlier because it clips the transient. That meant clicking
in and retyping nine characters, which is slower and less precise than
dragging the region again, so the fields went unused for the one job they
are best at. The wheel now adjusts them, in seconds left of the decimal
point and milliseconds right of it, a tenth and a hundredth of a second
per notch. One millisecond per notch would need a hundred notches to
cover something audible. Character-level hit-testing inside an input is
not reliable across browsers, but only the decimal point matters, so the
text up to it is measured and compared. A nudge past either end of the
track, or one that would squeeze the loop under the minimum, is dropped
rather than clamped, so holding the wheel at the end does not drag the
other bound along.

The panel row read "Click to collapse" as a sentence it had no width for,
and All was fused to it. The label is one word now, the rule sits after
it, and All is the first of four buttons. Its pressed state greys and
strikes it through like the other three, but only once all four are away:
read as "is anything hidden" it struck itself through the moment Analysis
was hidden alone, which looks exactly like you pressed it.

Loop stands beside the two bounds rather than over them. As a row of its
own it stretched the footer to three lines for one button.

The Alpha badge is gone from Click track. The feature has been through
several releases and is covered by its own spec; a warning that has
stopped being true also teaches people to ignore the next one. Removed
properly: markup, the CSS rule that had no other user, and the dead
click.alpha key in all ten tables.
@thcp thcp changed the title Clear the studio down to the mixer in one press Footer: scroll a loop bound, collapse everything at once, drop the Alpha badge Sep 1, 2026
@thcp
thcp merged commit e5cdaa0 into 0.16.1 Sep 1, 2026
8 checks passed
@thcp
thcp deleted the feat/collapse-all-panels branch September 1, 2026 10:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant